In this chapter we'll show a step-by-step C# example of creating, refreshing, retrieving, updating and deleting a Procedure by using the FhirClient.
Before we can do anything else, we have to create a new FhirClient. This is done by passing the url of the FHIR server's endpoint as a parameter to the constructor:
var client = new FhirClient("http://spark.furore.com/fhir");
You'll create an instance of FhirClient for every server you want to work with. In fact, every call we'll do on this client will be for resources and operations on this server. Since resources may reference other resources on a different FHIR server, you'll have to inspect any references and direct them to the right FhirClient. Of course, if you're dealing with a single server within your organization or a single cloud-based FHIR server, you don't have to worry about this.
Next, assume we have created a new Procedure and now we want to ask the FHIR server to store it for us. This is done by calling Create() on the FhirClient:
var report = new Procedure() { /* set up data */ };
var entry = client.Create<Procedure>(report);
As you'd probably expect, this operation will throw an exception when things go wrong, in most cases a FhirOperationException. This exception has an Outcome property of type OperationOutcome, which you may inspect to find out more information about why the operation failed. Most FHIR servers will return a human-readable error description in the OperationOutcome to help you out.
If the operation was successful, it will return an instance of ResourceEntry<Procedure>. By default this ResourceEntry contains only the metadata of the just created Resource, like its server-assigned id, version number and last modified date, but not the Resource's actual data. Since you already have the Procedure's data at hand, the server will, by default, not bother to return a copy of the data to save bandwidth. So, although the ResourceEntry's Id and LastUpdated and other metadata properties will be set, its Resource property will still be null. To get a copy of the resource as it was stored on the server, pass true as the value of the refresh parameter to the Create operation.
client.Create<Procedure>(new Procedure(), null, true);
Whenever you have held a Resource for some time, its data may have changed on the server because of changes made by others. At any time, you can refresh your local copy of the data by calling Refresh on the FhirClient, passing it the ResourceEntry as returned by a previous Read or Create:
var newEntry = client.Refresh(oldEntry);
This call will go to the server and fetch the latest version and metadata of the Resource as pointed to by the Id property in the ResourceEntry passed as the parameter.
To retrieve the data of an existing Procedure instance from a server, you'll need its web address (url). You may have previously stored this reference, or you may have found its address in a ResourceReference (e.g. MessageHeader.data.reference).
The Read operation on the FhirClient has two overloads to cover both cases. Furthermore, it accepts both relative paths and absolute paths (as long as they are within the endpoint passed to the constructor of the FhirClient). As with the other operations, Read returns a typed ResourceEntry rather than the Resource itself:
// Read the current version of a Resource
var locationA = new Uri("http://spark.furore.com/fhir/Procedure/31");
var reportEntryA = client.Read<Procedure>(location);
var reportEntryA = client.Read<Procedure>("Procedure/31");
// Read a specific version of a Resource
var locationB = new Uri("http://spark.furore.com/fhir/Procedure/32/_history/4");
var reportEntryB = client.Read<Procedure>(locationB);
var reportEntryB = client.Read<Procedure>("Procedure/32/_history/4");
Read only takes urls as parameters, so if you have the Resource name and its id as distinct data variables, use ResourceIdentity:
var reportEntryA = client.Read<Patient>(ResourceIdentity.Build("Procedure","31"));
Note that Read can be used to get the most recent version of a Resource as well as a specific version, and thus covers the two 'logical' REST operations read and vread.
Once you have retrieved a Procedure, you may edit its contents and send it back to the server. This is done using the Update operation. It takes the ResourceEntry previously retrieved as a parameter:
var location = new Uri("http://spark.furore.com/fhir/Procedure/31");
var reportEntryA = client.Read<Procedure>(location);
// Set the conclusion of the Procedure, and update
reportEntryA.Resource.outcome = "SomeOutcome";
client.Update(reportEntryA);
There's always a chance that between retrieving the resource and sending an update, someone else has updated the resource as well. Servers supporting version-aware updates may refuse your update in this case and return a HTTP status code 409 (Conflict), which causes the Update operation to throw a FhirOperationException with the same status code.
The Delete operation on the FhirClient deletes a resource from the server. It's up to the server to decide whether the resource is actually removed from storage, or whether previous versions are still available for retrieval. The Delete operation has multiple overloads to allow you to delete based on an url or a ResourceEntry:
var location = new Uri("http://spark.furore.com/fhir/Procedure/34");
client.Delete(location);
// You may also delete based on an existing ResourceEntry
client.Delete(reportEntry);
The Delete operation will fail and throw a FhirOperationException if the Resource was already deleted or if the Resource did not exist before deletion.
Note that sending an update to a Resource after is has been deleted is not considered an error and may effectively "undelete" it.